home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccppcsrc.lha / vbcc / vlink / targets.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  26KB  |  906 lines

  1. /* $VER: vlink targets.c V0.6c (05.02.99)
  2.  *
  3.  * This file is part of vlink, a portable linker for multiple
  4.  * object formats.
  5.  * Copyright (c) 1997-99  Frank Wille
  6.  *
  7.  * vlink is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
  9.  * vlink may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  *
  16.  * v0.6c (05.02.99) phx
  17.  *       ctors/dtors sections always start with 0xffffffff to provide
  18.  *       compatibility with most file formats (e.g. ELF).
  19.  * v0.6a (19.12.98) phx
  20.  *       Support for little endian object file formats.
  21.  *       readsection()/writesection() obey current endianess of linking
  22.  *       process.
  23.  *       make_priptr_objects() updates linker symbols during add_da-
  24.  *       ta_section().
  25.  * v0.6  (24.10.98) phx
  26.  *       find_lnksec() finds a LinkedSection by its name and/or type
  27.  *       (needed for ELF small data support).
  28.  *       New target elf32powerup, which supports the PPC coprocessor
  29.  *       boards from Phase5.
  30.  * v0.5e (05.10.98) phx
  31.  *       new_priptr(), add_priptrs(), make_priptr_objects(). Support for
  32.  *       artificial sections and objects, containing longwords sorted by
  33.  *       priority. These sections are automatically terminated by a NULL
  34.  *       pointer entry. Currently only used by ados-target for constructor
  35.  *       and destructor function pointer lists (__ctors, __dtors).
  36.  * v0.5c (08.07.98) phx
  37.  *       art_objunit() creates an artificial ObjectUnit + LinkFile.
  38.  * v0.5  (27.06.98) phx
  39.  *       addlnksymbol(), findlnksymbol() for target-specific linker
  40.  *       symbol support.
  41.  *       smalldata_section() returns a pointer to the first section,
  42.  *       which is referenced base relative.
  43.  * v0.3  (17.04.98) phx
  44.  *       addlocsymbol() allows multiple defintions of local
  45.  *       symbols with the same name.
  46.  *       addreloc() adds another relocation to a section.
  47.  *       relocsize() determines size in bytes of a relocation type.
  48.  *       addxref() requires the addend as additional argument.
  49.  *       ar-support functions for library archives.
  50.  * v0.1  (27.02.98) phx
  51.  *       First version that seems to link AmigaOS ADOS and EHF
  52.  *       objects and libraries. Many common features, like linking
  53.  *       sections together which have relative references, are
  54.  *       still missing. Also, PowerPC-ELF32 support is about to come.
  55.  * v0.0  (05.08.97) phx
  56.  *       File created.
  57.  */
  58.  
  59.  
  60. #define TARGETS_C
  61. #include "vlink.h"
  62.  
  63.  
  64. unsigned long findsecbase(struct GlobalVars *,char *);
  65. struct Symbol *findsymbol(struct GlobalVars *,char *name);
  66. struct Symbol *addsymbol(struct GlobalVars *,struct Section *,char *,
  67.                          uint32,uint8,uint8,uint8,uint8,uint32);
  68. void addlocsymbol(struct GlobalVars *,struct Section *,char *,uint32,
  69.                   uint8,uint8,uint8,uint32);
  70. void addglobsym(struct GlobalVars *,struct Symbol *);
  71. struct Symbol *addlnksymbol(struct FFFuncs *,struct Section *,char *,
  72.                             uint32,uint8,uint8,uint8,uint8,uint32);
  73. struct Symbol *findlnksymbol(struct FFFuncs *,char *);
  74. void addreloc(struct Section *,struct Section *,uint32,uint32,uint8,int32);
  75. void addxref(struct GlobalVars *,struct Section *,char *,uint32,uint8,
  76.              uint8,int32);
  77. int32 readsection(struct GlobalVars *,uint8 *,uint8);
  78. void writesection(struct GlobalVars *,uint8 *,uint8,uint32);
  79. uint8 relocsize(uint8);
  80. struct Section *create_section(struct ObjectUnit *,char *,uint8 *,
  81.                                unsigned long);
  82. struct Section *find_sect_type(struct ObjectUnit *,uint8,uint8);
  83. struct Section *find_sect_id(struct ObjectUnit *,uint32);
  84. struct LinkedSection *find_lnksec(struct GlobalVars *,char *,uint8,
  85.                                   uint8,uint8);
  86. struct LinkedSection *smalldata_section(struct GlobalVars *);
  87. void add_objunit(struct GlobalVars *,struct ObjectUnit *,bool);
  88. struct ObjectUnit *create_objunit(struct LinkFile *,char *);
  89. struct ObjectUnit *art_objunit(char *,uint8 *,unsigned long,uint8);
  90. void new_priptr(struct ObjectUnit *,char *,char *,int,char *,uint32);
  91. void add_priptrs(struct GlobalVars *,struct ObjectUnit *);
  92. void make_priptr_objects(struct GlobalVars *);
  93. bool ar_init(struct ar_info *,char *,unsigned long,char *);
  94. bool ar_extract(struct ar_info *);
  95.  
  96. static struct Section *getsecptr(struct list *,uint32);
  97. static struct Section *add_data_section(struct GlobalVars *,
  98.                                         struct ObjectUnit *,char *,uint8 *,
  99.                                         unsigned long);
  100.  
  101.  
  102. struct FFFuncs *fff[] = {
  103. #ifdef ADOS
  104.   &fff_amigaos,
  105. #endif
  106. #ifdef EHF
  107.   &fff_ehf,
  108. #endif
  109. #ifdef ELF32_PPC_BE
  110.   &fff_elf32ppcbe,
  111. #endif
  112. #ifdef ELF32_POWERUP
  113.   &fff_elf32powerup,
  114. #endif
  115.   NULL
  116. };
  117.  
  118. const char *sym_type[] = { "undef","abs","reloc","common" };
  119. const char *sym_info[] = { ""," object"," function"," section"," file" };
  120. const char *sym_bind[] = { "","local ","global ","weak " };
  121.  
  122.  
  123.  
  124. unsigned long findsecbase(struct GlobalVars *gv,char *name)
  125. /* scan the secbases list for a base address definition */
  126. {
  127.   struct SecBase *sb = gv->secbases;
  128.  
  129.   while (sb) {
  130.     if (!strcmp(name,sb->name))
  131.       return (sb->base);
  132.     sb = sb->next;
  133.   }
  134. }
  135.  
  136.  
  137. struct Symbol *findsymbol(struct GlobalVars *gv,char *name)
  138. /* return pointer to Symbol, if present */
  139. {
  140.   struct Symbol *sym = gv->symbols[elf_hash(name)%SYMHTABSIZE];
  141.  
  142.   while (sym) {
  143.     if (!strcmp(name,sym->name))
  144.       return (sym);  /* symbol found! */
  145.     sym = sym->glob_chain;
  146.   }
  147.   return (NULL);
  148. }
  149.  
  150.  
  151. struct Symbol *addsymbol(struct GlobalVars *gv,struct Section *s,char *name,
  152.                          uint32 val,uint8 type,uint8 flags,uint8 info,
  153.                          uint8 bind,uint32 size)
  154. /* Define a new symbol. If defined twice in the same object unit, then */
  155. /* return a pointer to its first definition. Defining the symbol twice */
  156. /* globally, is only allowed in different object units of a library. */
  157. {
  158.   struct Symbol *sym;
  159.   struct ObjectUnit *ou = s->obj;
  160.   struct Symbol **chain = &s->obj->objsyms[elf_hash(name)%OBJSYMHTABSIZE];
  161.  
  162.   while (sym = *chain) {
  163.     if (!strcmp(name,sym->name))
  164.       return (sym);  /* symbol already defined - don't define it twice */
  165.       /* The target-specific routines have to handle this case. */
  166.     chain = &sym->obj_chain;
  167.   }
  168.  
  169.   *chain = sym = alloc(sizeof(struct Symbol));
  170.   sym->glob_chain = sym->obj_chain = NULL;
  171.   sym->name = name;
  172.   sym->value = val;
  173.   sym->relsect = s;
  174.   sym->type = type;
  175.   sym->flags = flags;
  176.   sym->info = info;
  177.   sym->bind = bind;
  178.   sym->size = size;
  179.  
  180.   if (bind==SYMB_GLOBAL || bind==SYMB_WEAK)
  181.     addglobsym(gv,sym);
  182.  
  183.   return (NULL);  /* ok, new symbol was created */
  184. }
  185.  
  186.  
  187. void addlocsymbol(struct GlobalVars *gv,struct Section *s,char *name,
  188.                   uint32 val,uint8 type,uint8 flags,uint8 info,uint32 size)
  189. /* Define a new local symbol. Local symbols are allowed to be */
  190. /* multiply defined. */
  191. {
  192.   struct Symbol *sym;
  193.   struct Symbol **chain = &s->obj->objsyms[elf_hash(name)%OBJSYMHTABSIZE];
  194.  
  195.   while (sym = *chain)
  196.     chain = &sym->obj_chain;
  197.   *chain = sym = alloc(sizeof(struct Symbol));
  198.   sym->glob_chain = sym->obj_chain = NULL;
  199.   sym->name = name;
  200.   sym->value = val;
  201.   sym->relsect = s;
  202.   sym->type = type;
  203.   sym->flags = flags;
  204.   sym->info = info;
  205.   sym->bind = SYMB_LOCAL;
  206.   sym->size = size;
  207. }
  208.  
  209.  
  210. void addglobsym(struct GlobalVars *gv,struct Symbol *newsym)
  211. /* insert symbol into global symbol hash table */
  212. {
  213.   struct Symbol **chain = &gv->symbols[elf_hash(newsym->name)%SYMHTABSIZE];
  214.   struct Symbol *sym;
  215.   struct ObjectUnit *newou = newsym->relsect->obj;
  216.  
  217.   while (sym = *chain) {
  218.     if (!strcmp(newsym->name,sym->name)) {
  219.       if (sym->bind == SYMB_GLOBAL) {
  220.         /* symbol already defined with global binding */
  221.         if (newsym->bind==SYMB_GLOBAL && newou->lnkfile->type<ID_LIBBASE) {
  222.           if (newsym->type==SYM_COMMON && sym->type==SYM_COMMON) {
  223.             if (newsym->size > sym->size) {
  224.               /* replace by common symbol with